package com.ruoyi.assets.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.assets.domain.StateAsset;
import com.ruoyi.assets.domain.dto.StateAssetQueryDto;
import com.ruoyi.assets.mapper.StateAssetMapper;
import com.ruoyi.assets.service.IStateAssetService;
import com.ruoyi.assets.service.IStateVisitService;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysConfigService;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

/**
 * 资产Service业务层处理
 * 
 * @author ruoyi
 */
@Service
public class StateAssetServiceImpl extends ServiceImpl<StateAssetMapper, StateAsset> implements IStateAssetService {
    private static final Logger log = LoggerFactory.getLogger(StateAssetServiceImpl.class);
    
    @Autowired
    private IStateVisitService stateVisitService;
    
    @Autowired
    private StateAssetMapper stateAssetMapper;

    @Autowired
    private ISysConfigService sysConfigService;
    
    /**
     * 查询资产列表
     * 
     * @param queryDto 查询条件
     * @return 资产列表
     */
    @Override
    public List<StateAsset> selectStateAssetList(StateAssetQueryDto queryDto) {
        return stateAssetMapper.selectStateAssetList(queryDto);
    }
    
    /**
     * 通过ID查询资产
     * 
     * @param id 资产ID
     * @return 资产信息
     */
    @Override
    public StateAsset selectStateAssetById(Long id) {
        return getById(id);
    }
    
    /**
     * 新增资产
     * 
     * @param stateAsset 资产信息
     * @return 结果
     */
    @Override
    public boolean insertStateAsset(StateAsset stateAsset) {
        // 处理街道信息
        processStreetName(stateAsset);
        // 处理地址获取经纬度
        processLocationByAddress(stateAsset);
        return save(stateAsset);
    }
    
    /**
     * 修改资产
     * 
     * @param stateAsset 资产信息
     * @return 结果
     */
    @Override
    public boolean updateStateAsset(StateAsset stateAsset) {
        // 处理街道信息
        processStreetName(stateAsset);
        // 处理地址获取经纬度
        processLocationByAddress(stateAsset);
        return updateById(stateAsset);
    }
    
    /**
     * 处理街道名称
     * 
     * @param stateAsset 资产信息
     */
    private void processStreetName(StateAsset stateAsset) {
        if (StringUtils.isNotEmpty(stateAsset.getAddress())) {
            // 获取街道字典数据
            List<SysDictData> streetDictList = DictUtils.getDictCache("sys_street");
            if (streetDictList != null && !streetDictList.isEmpty()) {
                for (SysDictData dictData : streetDictList) {
                    String dictValue = dictData.getDictValue();
                    // 判断地址中是否包含字典键值
                    String streetName = dictValue.replace("街道", "");
                    if (stateAsset.getAddress().contains(streetName)) {
                        // 设置街道名称
                        stateAsset.setStreetName(streetName);
                        break;
                    }
                }
            }
        }
    }
    
    /**
     * 处理地址获取经纬度
     * 
     * @param stateAsset 资产信息
     */
    private void processLocationByAddress(StateAsset stateAsset) {
        if (StringUtils.isNotEmpty(stateAsset.getAddress())) {
            // 获取资产ID并查询原始资产数据
            boolean addressChanged = false;
            
            // 如果有ID，则比较地址是否发生变化
            if (stateAsset.getId() != null) {
                StateAsset originalAsset = getById(stateAsset.getId());
                if (originalAsset != null && !stateAsset.getAddress().equals(originalAsset.getAddress())) {
                    addressChanged = true;
                    log.info("资产[{}]地址已变更，原地址：{}，新地址：{}", stateAsset.getName(), 
                            originalAsset.getAddress(), stateAsset.getAddress());
                }
            }
            
            // 如果经纬度为空或者地址发生变化，则重新获取经纬度
            if (StringUtils.isBlank(stateAsset.getLongitude()) || StringUtils.isBlank(stateAsset.getLatitude()) || addressChanged) {
                // 从系统配置获取高德地图API密钥
                String amapKey = sysConfigService.selectConfigByKey("amapKey");
                if (StringUtils.isNotBlank(amapKey)) {
                    GeoUtils.setKey(amapKey);

                    // 从地址获取经纬度
                    String[] location = GeoUtils.getLocationByAddress(stateAsset.getAddress());
                    if (location != null && location.length == 2) {
                        stateAsset.setLongitude(location[0]); // 经度
                        stateAsset.setLatitude(location[1]);  // 纬度
                        log.info("成功获取资产[{}]的经纬度：[{}, {}]", stateAsset.getName(), location[0], location[1]);
                    } else {
                        log.warn("无法获取资产[{}]的经纬度，地址：{}", stateAsset.getName(), stateAsset.getAddress());
                    }
                }
            } else {
                // 如果已有经纬度，且地址未变化，则保留原值
                log.info("资产[{}]已有经纬度：[{}, {}]，保留原值", stateAsset.getName(), stateAsset.getLongitude(), stateAsset.getLatitude());
            }
        }
    }
    
    /**
     * 处理评估时间格式
     * 
     * @param stateAsset 资产信息
     */
    private void processEvaluationTime(StateAsset stateAsset) {
        if (StringUtils.isNotEmpty(stateAsset.getEvaluationTime())) {
            String evaluationTime = stateAsset.getEvaluationTime().trim();
            
            // 使用增强版日期解析（支持Java Date toString格式）
            Date date = DateUtils.parseDateEnhanced(evaluationTime);
            if (date != null) {
                // 转换为标准格式 yyyy-MM-dd
                String formattedDate = DateUtils.parseDateToStr("yyyy-MM-dd", date);
                stateAsset.setEvaluationTime(formattedDate);
                log.info("资产[{}]评估时间已格式化：{} -> {}", stateAsset.getName(), evaluationTime, formattedDate);
            } else {
                log.warn("资产[{}]评估时间格式无法识别，保持原值：{}", stateAsset.getName(), evaluationTime);
            }
        }
    }
    
    /**
     * 批量删除资产
     * 
     * @param ids 需要删除的资产ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteStateAssetByIds(List<Long> ids) {
        return removeByIds(ids);
    }
    
    /**
     * 删除资产信息
     * 
     * @param id 资产ID
     * @return 结果
     */
    @Override
    public boolean deleteStateAssetById(Long id) {
        return removeById(id);
    }
    
    /**
     * 批量审核资产
     * 
     * @param ids 资产ID列表
     * @param auditStatus 审核状态
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchAuditStateAsset(List<Long> ids, Integer auditStatus) {
        LambdaUpdateWrapper<StateAsset> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(StateAsset::getId, ids)
                    .set(StateAsset::getAuditStatus, auditStatus)
                    .set(StateAsset::getUpdateBy, SecurityUtils.getUsername())
                    .set(StateAsset::getUpdateTime, DateUtils.getNowDate());
        return update(updateWrapper);
    }
    
    /**
     * 导入资产数据
     *
     * @param file 导入文件
     * @param updateSupport 是否更新已存在数据
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importStateAsset(MultipartFile file, boolean updateSupport) {
        try {
            ExcelUtil<StateAsset> util = new ExcelUtil<>(StateAsset.class);
            List<StateAsset> assetList = util.importExcel(file.getInputStream());
            if (StringUtils.isNull(assetList) || assetList.size() == 0) {
                throw new ServiceException("导入资产数据不能为空！");
            }
            
            List<StateAsset> insertList = new ArrayList<>();
            List<StateAsset> updateList = new ArrayList<>();
            for (StateAsset asset : assetList) {
                if (StringUtils.isBlank(asset.getName())) {
                    throw new ServiceException("导入资产数据失败，资产名称不能为空");
                }
                
                // 处理街道信息
                processStreetName(asset);
                processLocationByAddress(asset);
                // 处理评估时间格式
                processEvaluationTime(asset);
                // 验证是否存在这个资产
                LambdaQueryWrapper<StateAsset> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(StateAsset::getName, asset.getName());
                StateAsset existAsset = getOne(queryWrapper);
                
                if (StringUtils.isNull(existAsset)) {
                    insertList.add(asset);
                } else if (updateSupport) {
                    asset.setId(existAsset.getId());
                    updateList.add(asset);
                } else {
                    throw new ServiceException("导入资产数据失败，资产" + asset.getName() + "已存在");
                }
            }
            
            if (!insertList.isEmpty()) {
                saveBatch(insertList);
            }
            if (!updateList.isEmpty()) {
                updateBatchById(updateList);
            }
            
            return "导入成功，共 " + assetList.size() + " 条数据，其中新增 " + insertList.size() + " 条，更新 " + updateList.size() + " 条";
        } catch (Exception e) {
            log.error("导入资产数据失败：", e);
            throw new ServiceException("导入资产数据失败：" + e.getMessage());
        }
    }
    
    /**
     * 导出资产数据
     *
     * @param response 响应
     * @param queryDto 查询条件
     */
    @Override
    public void exportStateAsset(HttpServletResponse response, StateAssetQueryDto queryDto) {
        List<StateAsset> list = selectStateAssetList(queryDto);
        ExcelUtil<StateAsset> util = new ExcelUtil<>(StateAsset.class);
        util.exportExcel(response, list, "资产数据");
    }
    
    /**
     * 获取资产统计数据
     * 
     * @return 资产统计数据
     */
    @Override
    public Map<String, Object> getAssetStatistics() {
        Map<String, Object> result = new HashMap<>();
        
        // 1. 获取按状态统计的资产数量
        Map<String, Object> statusCounts = baseMapper.countAssetsByStatus();
        
        // 2. 计算空置率
        int totalCount = Integer.parseInt(statusCounts.get("total_count").toString());
        int forRentCount = Integer.parseInt(statusCounts.get("for_rent_count").toString());
        String vacancyRate = "0%";
        if (totalCount > 0) {
            double rate = (double) forRentCount / totalCount * 100;
            vacancyRate = String.format("%.2f%%", rate);
        }
        
        // 3. 获取今日浏览量
        Integer todayVisits = stateVisitService.selectTodayTotalVisits();
        
        // 4. 获取按街道分组的资产统计
        List<Map<String, Object>> streetStats = baseMapper.countAssetsByStreet();
        
        // 5. 获取月度资产趋势数据
        Calendar calendar = Calendar.getInstance();
        // 获取12个月前的日期
        calendar.add(Calendar.MONTH, -12);
        Date startDate = calendar.getTime();
        Date endDate = new Date();
        List<Map<String, Object>> monthlyTrends = baseMapper.countAssetMonthlyTrend(startDate, endDate);
        
        // 构建返回数据结构
        result.put("totalCount", totalCount);
        result.put("maintenanceCount", statusCounts.get("maintenance_count"));
        result.put("forRentCount", forRentCount);
        result.put("rentedCount", statusCounts.get("rented_count"));
        result.put("vacancyRate", vacancyRate);
        result.put("todayVisits", todayVisits);
        result.put("streetStats", streetStats);
        result.put("monthlyTrends", monthlyTrends);
        
        // 添加访问量趋势数据
        List<Map<String, Object>> visitTrends = stateVisitService.getMonthlyVisitTrends(12);
        result.put("visitTrends", visitTrends);
        
        return result;
    }
} 